package tjs.study.notes.base.common;

import java.util.Random;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;

public class TestBuiUtils {
    private String desc = UUID.randomUUID().toString();//测试任务描述
    private int times = 20;//测试次数
    private int threadNum = 20;//测试线程总数
    private FunctionTest functionTest = null;//自定义目标方法

    private long max;
    private long min;
    private long avg;
    private long sum;
    private StringBuilder res;

    public TestBuiUtils() {
    }

    public TestBuiUtils(String desc) {
        this.desc = desc;
    }

    public TestBuiUtils(String desc, FunctionTest functionTest) {
        this.desc = desc;
        this.functionTest = functionTest;
    }

    public TestBuiUtils doTestThread(FunctionTest functionTest) {
        this.doTest((item) -> {
            final CountDownLatch countDownHasStart = new CountDownLatch(threadNum);
            final CountDownLatch countDownHasFinsh = new CountDownLatch(threadNum);
            for (int j = 0; j < threadNum; j++) {
                try {
                    int finalJ = j;
                    new Thread(() -> {
                        //执行目标方法
                        try {
                            countDownHasStart.await();
                            functionTest.doTest(finalJ);
                        } catch (Throwable throwable) {
                            throwable.printStackTrace();
                        }
                        countDownHasFinsh.countDown();
                    }).start();
                    countDownHasStart.countDown();
                } catch (Throwable throwable) {
                    throwable.printStackTrace();
                }
            }
            countDownHasFinsh.await();
        });
        return this;
    }

    public TestBuiUtils doTestThread() {
        this.doTestThread(this.functionTest);
        return this;
    }

    public TestBuiUtils doTest(FunctionTest functionTest) {
        if (functionTest == null) {
            throw new RuntimeException("请定义目标方法");
        }
        this.res = new StringBuilder();
        this.max = Long.MIN_VALUE;
        this.min = Long.MAX_VALUE;
        for (int i = 0; i < times; i++) {
            long start = System.currentTimeMillis();
            //执行目标方法
            try {
                functionTest.doTest(i);
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
            long duration = (System.currentTimeMillis() - start);
            this.res.append(i).append(": ").append(duration).append(";  ");
            this.max = this.max < duration ? duration : this.max;
            this.min = this.min > duration ? duration : this.min;
            this.sum = this.sum + duration;
        }
        this.avg = this.sum / this.times;
        return this;
    }

    public TestBuiUtils doTest() {
        this.doTest(this.functionTest);
        return this;
    }

    public void printAll() {
        System.out.println("测试任务: " + this.desc + ">>>\nmax:" + this.max + "; min:" + this.min + "; avg:" + this.avg + "; sum:" + this.sum /*+ ";\ndetail:  " + this.res*/);
    }

    public void printAvg() {
        System.out.println("测试任务: " + this.desc + ">>>\navg:" + this.avg);
    }

    public StringBuilder getRes() {
        return res;
    }

    public TestBuiUtils desc(String desc) {
        this.desc = desc;
        return this;
    }

    public TestBuiUtils times(int times) {
        this.times = times;
        return this;
    }

    public TestBuiUtils threadNum(int threadNum) {
        this.threadNum = threadNum;
        return this;
    }

    public TestBuiUtils functionTest(FunctionTest functionTest) {
        this.functionTest = functionTest;
        return this;
    }

    public static void main(String[] args) {
        int incre = 9999;
        final int size = 99999999;
        int[] a = new int[size];
        for (int i = 0; i < size; i++) {
            a[i] = new Random().nextInt(100000);
        }

        int times = 10;
        new TestBuiUtils().desc("systemCopy").times(times).functionTest((taskNum) -> {
            int[] b = new int[a.length + incre];//新数组
            System.arraycopy(a, 0, b, 0, a.length);
        }).doTest().printAll();

        new TestBuiUtils().desc("forCopy").times(times).functionTest((taskNum) -> {
            int[] b = new int[a.length + incre];//新数组
            for (int i = 0; i < size; i++) {
                b[i] = a[i];
            }
        }).doTest().printAll();
    }
}
